package com.party.admin.biz.mall;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.party.admin.biz.refund.RefundBizService;
import com.party.common.constant.Constant;
import com.party.common.paging.Page;
import com.party.common.utils.BigDecimalUtils;
import com.party.common.utils.PartyCode;
import com.party.common.utils.StringUtils;
import com.party.core.exception.BusinessException;
import com.party.core.exception.OrderException;
import com.party.core.model.logistics.WlLogisticsStatus;
import com.party.core.model.mall.*;
import com.party.core.model.member.Member;
import com.party.core.model.order.*;
import com.party.core.service.logistics.IWlLogisticsService;
import com.party.core.service.mall.IMallGoodsService;
import com.party.core.service.mall.IMallOrderDetailService;
import com.party.core.service.mall.IMallStoreService;
import com.party.core.service.mall.biz.MallDataBizService;
import com.party.core.service.mall.biz.ProductBizService;
import com.party.core.service.mall.impl.MallGoodsService;
import com.party.core.service.member.IMemberService;
import com.party.core.service.order.IOrderFormService;
import com.party.core.service.order.IOrderRefundTradeService;
import com.party.core.service.order.IOrderTradeService;
import com.party.pay.model.refund.WechatPayRefundResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 商品订单业务接口
 * Created by wei.li
 *
 * @date 2017/8/16 0016
 * @time 11:06
 */
@Service
public class MallOrderBizService {

    @Autowired
    private IMallOrderDetailService mallOrderDetailService;

    @Autowired
    private RefundBizService refundBizService;

    @Autowired
    private IOrderRefundTradeService orderRefundTradeService;

    @Autowired
    private IOrderFormService orderFormService;

    @Autowired
    private IMemberService memberService;

    @Autowired
    private ProductBizService productBizService;

    @Autowired
    private IOrderTradeService orderTradeService;

    @Autowired
    private IMallStoreService mallStoreService;

    @Autowired
    private MallDataBizService mallDataBizService;

    @Autowired
    private IWlLogisticsService wlLogisticsService;

    @Autowired
    private IMallGoodsService mallGoodsService;


    @Value("#{kuaidiniao['kuaidiniao.eBusinessID']}")
    private String eBusinessID;

    @Value("#{kuaidiniao['kuaidiniao.apiKey']}")
    private String apiKey;

    Logger logger = LoggerFactory.getLogger(getClass());


    /**
     * 退款审核
     *
     * @param orderDetailId 子订单id
     * @param status        状态 1：同意 2：拒绝
     * @throws Exception
     */
    public void checkRefund(String orderDetailId, Integer status) throws Exception {
        MallOrderDetail orderDetail = mallOrderDetailService.get(orderDetailId);
        if (orderDetail == null) {
            throw new BusinessException("订单为空");
        }

        if (status == 2) { // 拒绝
            orderDetail.setStatus(MallOrderDetailStatus.STATUS_REFUND_REJECT.getCode());
            mallOrderDetailService.update(orderDetail);
        } else {
            String orderId = orderDetail.getOrderId();
            double total = BigDecimalUtils.mul(orderDetail.getPrice() * orderDetail.getQuantity(), 100);
            total = BigDecimalUtils.round(total, 2);
            Object responseData = refundBizService.refund(orderId, (int) total);
            if (responseData != null) {
                WechatPayRefundResponse response = (WechatPayRefundResponse) responseData;

                // 退款成功
                if (Constant.WECHAT_SUCCESS.equals(response.getReturnCode())
                        && Constant.WECHAT_SUCCESS.equals(response.getResultCode())) {
                    refundCallback(orderId, orderDetailId, response);
                }
            } else {
                throw new BusinessException("退款失败");
            }
        }
    }

    /**
     * 退款回调
     *
     * @param orderId       订单编号
     * @param orderDetailId 订单详情编号
     * @param response      响应参数
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void refundCallback(String orderId, String orderDetailId, WechatPayRefundResponse response) {
        try {
            // 更改订单详情状态 (子订单)为退款成功
            MallOrderDetail orderDetail = mallOrderDetailService.get(orderDetailId);
            orderDetail.setStatus(MallOrderDetailStatus.STATUS_REFUND_SUCCESS.getCode());
            mallOrderDetailService.update(orderDetail);

            Long count = mallOrderDetailService.getNotRefund(orderDetail.getParentId(), MallOrderDetailStatus.STATUS_REFUND_SUCCESS.getCode(), null);
            if (count == 0) {
                // 更改主订单状态为已关闭
                MallOrderDetail odParent = mallOrderDetailService.get(orderDetail.getParentId());
                odParent.setStatus(MallOrderDetailStatus.STATUS_CLOSED.getCode());
                mallOrderDetailService.update(odParent);
            }

            Long totalCount = mallOrderDetailService.getNotRefund(null, MallOrderDetailStatus.STATUS_REFUND_SUCCESS.getCode(), orderId);
            if (totalCount == 0) {
                // 更改订单状态为已退款
                OrderForm orderForm = orderFormService.get(orderId);
                orderForm.setStatus(OrderStatus.ORDER_STATUS_REFUND.getCode());
                orderFormService.update(orderForm);
            }

            if (StringUtils.isNotEmpty(orderDetail.getDistributorId())) {
                try {
                    MallDataCount mallDataCount = new MallDataCount();
                    mallDataCount.setMemberId(orderDetail.getDistributorId());
                    if (0 == count) {
                        mallDataCount.setOrderNum(1);
                    }
                    mallDataCount.setTurnover(new BigDecimal(orderDetail.getPrice()));
                    mallDataCount.setSalesNum(orderDetail.getQuantity());
                    mallDataCount.setIncome(new BigDecimal(orderDetail.getPrice() - orderDetail.getTradePrice()));
                    mallDataCount.setCreateBy(orderDetail.getDistributorId());
                    mallDataCount.setUpdateBy(orderDetail.getDistributorId());

                    mallDataBizService.calcDataCount(mallDataCount, false);
                } catch (Exception e) {
                    logger.error("退款时, 统计商城数据异常", e);
                }

                try {
                    mallDataBizService.reviseNow(orderDetail.getDistributorId());
                } catch (Exception e) {
                    logger.error("退款时, 矫正统计商城数据异常", e);
                }
            }

            // 处理商品库存、销量
            productBizService.refundUpdateSalesNumAndStock(orderDetail.getProductId(), orderDetail.getQuantity());

            // 保存退款流水
            String transactionId = response.getTransactionId();
            String responseData = JSONObject.toJSONString(response);
            OrderRefundTrade orderTrade = new OrderRefundTrade();
            orderTrade.setOrderFormId(orderId);
            orderTrade.setOrigin(OrderOrigin.ORDER_ORIGIN_MALL.getCode());
            orderTrade.setTransactionId(transactionId);
            orderTrade.setType(PaymentWay.WECHAT_PAY.getCode());
            orderTrade.setData(responseData);
            orderRefundTradeService.insert(orderTrade);
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("商城订单退款回调异常", e);
        }
    }

    /**
     * 更新状态为待收货
     *
     * @param orderId       主订单id
     * @param goodsTargetId 子订单id集合
     */
    public void updateShipmentStatus(String orderId, String goodsTargetId) {
        for (String childId : goodsTargetId.split(",")) {
            MallOrderDetail outputChild = mallOrderDetailService.get(childId);
            outputChild.setStatus(MallOrderDetailStatus.STATUS_HAVE_SHIPMENT.getCode());
            mallOrderDetailService.update(outputChild);
        }
        Integer notShipmentCount = 0;
        MallOrderOutputPay outputPay = mallOrderDetailService.findByOrderId(orderId);
        for (MallOrderOutputParent outputParent : outputPay.getChildrens()) {
            for (MallOrderOutputChild outputChild : outputParent.getChildrens()) {
                if (outputChild.getStatus().equals(MallOrderDetailStatus.STATUS_NOT_SHIPMENT.getCode())) {
                    notShipmentCount++;
                }
            }
        }
        if (notShipmentCount == 0) {
            Date shipmentDate = new Date();
            for (MallOrderOutputParent outputParent : outputPay.getChildrens()) {
                MallOrderDetail orderDetail = mallOrderDetailService.get(outputParent.getId());
                orderDetail.setStatus(MallOrderDetailStatus.STATUS_HAVE_SHIPMENT.getCode());
                orderDetail.setShipmentDate(shipmentDate);
                mallOrderDetailService.update(orderDetail);
            }
        }
    }

    /**
     * 订单详情
     *
     * @param orderId 支付订单id
     * @return
     */
    public Map<String, Object> getDetail(String orderId) {
        MallStore mallStore = mallStoreService.getUnique();
        Map<String, Object> result = Maps.newHashMap();
        // 未发货的商品
        List<MallOrderOutputParent> outputParents = mallOrderDetailService.listWithNotShipment(orderId);
        for (MallOrderOutputParent outputParent : outputParents) {
            List<MallOrderOutputChild> childrens = Lists.newArrayList();
            for (MallOrderOutputChild outputChild : outputParent.getChildrens()) {
                String value = MallOrderDetailStatus.getValue(outputChild.getStatus());
                outputChild.setStatusName(value);
                childrens.add(outputChild);
            }
            outputParent.setChildrens(childrens);
            this.transfromStoreName(mallStore, outputParent);
        }
        result.put("notShipmentOrderDetails", outputParents);
        // 已发货的包裹
        List<MallOrderWithLogisticsOutput> logisticsOutputs = mallOrderDetailService.listWithShipment(orderId);
        for (MallOrderWithLogisticsOutput output : logisticsOutputs) {
            if (null != output.getStatusEx()) {
                String value = WlLogisticsStatus.getValue(output.getStatusEx());
                output.setStatusName(value);
            } else if (null != output.getStatus()) {
                String value = WlLogisticsStatus.getValue(output.getStatus());
                output.setStatusName(value);
            }
            for (MallOrderDetail orderDetail : output.getChildrens()) {
                String value = MallOrderDetailStatus.getValue(orderDetail.getStatus());
                orderDetail.setStatusName(value);
            }
        }
        result.put("shipments", logisticsOutputs);
        MallOrderDetail outputPay = mallOrderDetailService.getUniqueByOrderId(orderId);
        Set<Integer> statusSet = mallOrderDetailService.findStatusByOrderId(orderId);
        this.transfromStatus(statusSet, outputPay);

        String value = MallOrderDetailStatus.getValue(outputPay.getStatus());
        outputPay.setStatusName(value);
        Member member = memberService.get(outputPay.getMemberId());
        OrderTrade orderTrade = orderTradeService.findByOrderId(outputPay.getOrderId());
        if (orderTrade != null) {
            result.put("payDate", orderTrade.getCreateDate());
            result.put("transactionId", orderTrade.getTransactionId());
        }
        result.put("outputPay", outputPay);
        result.put("buyer", member);

        //获取父订单
        List<MallOrderDetail> parentByOrderId = mallOrderDetailService.findParentByOrderId(orderId);
        //获取子订单
        MallOrderDetail detail = new MallOrderDetail();
        detail.setOrderId(orderId);
        detail.setParentId(parentByOrderId.get(0).getId());
        List<MallOrderDetail> list = mallOrderDetailService.list(detail);

        //获取订单中商品id
        String goodsId = list.get(0).getGoodsId();
        //获取订单商品信息
        MallGoods mallGoods = mallGoodsService.get(goodsId);

        //返回商品类型
        result.put("type",mallGoods.getType());

        return result;
    }

    /**
     * 支付完成后订单业务处理 更新状态及增加销量
     *
     * @param orderId 订单id
     * @throws Exception
     */
    public void payMall(String orderId) {
        MallOrderOutputPay orderOutputPay = mallOrderDetailService.findByOrderId(orderId);
        if (orderOutputPay == null) {
            throw new OrderException(PartyCode.IS_NO_DATA, "订单为空");
        }

        for (MallOrderOutputParent orderOut : orderOutputPay.getChildrens()) {
            MallOrderDetail pOut = mallOrderDetailService.get(orderOut.getId());
            pOut.setStatus(MallOrderDetailStatus.STATUS_NOT_SHIPMENT.getCode());
            mallOrderDetailService.update(pOut);

            for (MallOrderOutputChild childOut : orderOut.getChildrens()) {
                MallOrderDetail cOut = mallOrderDetailService.get(childOut.getId());
                cOut.setStatus(MallOrderDetailStatus.STATUS_NOT_SHIPMENT.getCode());
                mallOrderDetailService.update(cOut);

                productBizService.payUpdateSalesNum(cOut.getProductId(), cOut.getQuantity());
            }
        }
    }

    /**
     * admin订单列表
     *
     * @param orderDetail
     * @param payStatus
     * @param params
     * @param page
     * @return
     */
    public List<MallOrderOutputPay> webListPage(MallOrderDetail orderDetail, String payStatus, Map<String, Object> params, Page page) {
        if (StringUtils.isNotEmpty(payStatus)) {
            Set<Integer> status = Sets.newHashSet();
            status.add(MallOrderDetailStatus.STATUS_COMPLETE.getCode());
            status.add(MallOrderDetailStatus.STATUS_NOT_SHIPMENT.getCode());
            status.add(MallOrderDetailStatus.STATUS_HAVE_SHIPMENT.getCode());
            status.add(MallOrderDetailStatus.STATUS_REFUND_ING.getCode());
            status.add(MallOrderDetailStatus.STATUS_REFUND_REJECT.getCode());
            params.put("payStatus", status);
        }
        MallStore mallStore = mallStoreService.getUnique();
        List<MallOrderOutputPay> orderList = mallOrderDetailService.webListPage(orderDetail, params, page);
        for (MallOrderOutputPay outputPay : orderList) {
            Double totalPrice = 0d;
            Integer totalQuantity = 0;
            Integer childCount = 0;

            Set<Integer> statusSet = Sets.newHashSet();
            for (MallOrderOutputParent outputParent : outputPay.getChildrens()) {
                statusSet.add(outputParent.getStatus());
                Double totalProfit = 0d; // 总利润
                totalPrice = BigDecimalUtils.add(outputParent.getPrice(), totalPrice);
                totalQuantity += outputParent.getQuantity();
                for (MallOrderOutputChild outputChild : outputParent.getChildrens()) {
                    childCount++;
                    String statusName = MallOrderDetailStatus.getValue(outputChild.getStatus());
                    outputChild.setStatusName(statusName);

                    if (outputChild.getStatus().equals(MallOrderDetailStatus.STATUS_COMPLETE.getCode())
                            || outputChild.getStatus().equals(MallOrderDetailStatus.STATUS_NOT_SHIPMENT.getCode())
                            || outputChild.getStatus().equals(MallOrderDetailStatus.STATUS_HAVE_SHIPMENT.getCode())
                            || outputChild.getStatus().equals(MallOrderDetailStatus.STATUS_REFUND_ING.getCode())
                            || outputChild.getStatus().equals(MallOrderDetailStatus.STATUS_NOT_EVALUATE.getCode())
                            || outputChild.getStatus().equals(MallOrderDetailStatus.STATUS_REFUND_REJECT.getCode())) {
                        // 售价
                        Double price = BigDecimalUtils.mul(outputChild.getPrice(), outputChild.getQuantity());
                        // 批发价
                        Double tradePrice = outputChild.getTradePrice() == null ? 0d : outputChild.getTradePrice();
                        tradePrice = BigDecimalUtils.mul(tradePrice, outputChild.getQuantity());

                        double balance = BigDecimalUtils.sub(price, tradePrice);
                        totalProfit = BigDecimalUtils.add(totalProfit, balance);
                    }
                }
                outputParent.setTotalProfit(BigDecimalUtils.round(totalProfit, 2));
                this.transfromStoreName(mallStore, outputParent);
            }

            this.transfromStatus(statusSet, outputPay);

            outputPay.setChildCount(childCount);
            outputPay.setQuantity(totalQuantity);
            outputPay.setPrice(totalPrice);
            String statusName = MallOrderDetailStatus.getValue(outputPay.getStatus());
            outputPay.setStatusName(statusName);

            Integer totalCount = wlLogisticsService.getCountByOrderId(outputPay.getOrderId(), null);
            Integer signedCount = wlLogisticsService.getCountByOrderId(outputPay.getOrderId(), WlLogisticsStatus.HAVE_SIGNED.getCode());
            if (signedCount > 0 && signedCount.equals(totalCount)) {
                outputPay.setLogisticsStatus(WlLogisticsStatus.HAVE_SIGNED.getCode());
            }
        }
        return orderList;
    }

    public void transfromStatus(Set<Integer> statusSet, MallOrderOutputPay outputPay) {
        if (statusSet.size() > 1) { // 多个状态
            for (Integer status : statusSet) {
                if (!status.equals(MallOrderDetailStatus.STATUS_CLOSED.getCode())) {
                    outputPay.setStatus(status);
                    break;
                }
            }
        } else {
            outputPay.setStatus(statusSet.iterator().next());
        }
    }

    public void transfromStatus(Set<Integer> statusSet, MallOrderDetail outputPay) {
        if (statusSet.size() > 1) { // 多个状态
            for (Integer status : statusSet) {
                if (!status.equals(MallOrderDetailStatus.STATUS_CLOSED.getCode())) {
                    outputPay.setStatus(status);
                    break;
                }
            }
        } else {
            outputPay.setStatus(statusSet.iterator().next());
        }
    }

    /**
     * 渲染店铺名称
     *
     * @param mallStore    默认店铺
     * @param outputParent
     */
    public void transfromStoreName(MallStore mallStore, MallOrderOutputParent outputParent) {
        if (StringUtils.isEmpty(outputParent.getDistributorId())) {
            outputParent.setDistributorName(mallStore.getName());
        }
    }

    /**
     * 更新订单为已完成
     *
     * @param orderId
     */
    public void updateCompleteDate(String orderId) {
        Date completeDate = new Date();
        MallOrderOutputPay orderOutputPay = mallOrderDetailService.findByOrderId(orderId);
        for (MallOrderOutputParent outputParent : orderOutputPay.getChildrens()) {
            // 状态为待收货 才能改为已完成
            if (outputParent.getStatus().equals(MallOrderDetailStatus.STATUS_HAVE_SHIPMENT.getCode())) {
                MallOrderDetail pOut = mallOrderDetailService.get(outputParent.getId());
                pOut.setStatus(MallOrderDetailStatus.STATUS_COMPLETE.getCode());
                pOut.setCompleteDate(completeDate);
                mallOrderDetailService.update(pOut);

                for (MallOrderOutputChild childOut : outputParent.getChildrens()) {
                    MallOrderDetail cOut = mallOrderDetailService.get(childOut.getId());
                    cOut.setStatus(MallOrderDetailStatus.STATUS_COMPLETE.getCode());
                    mallOrderDetailService.update(cOut);
                }
            }
        }
    }

    /**
     * 确认收货
     *
     * @param orderId 支付订单id
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void receiveShipment(String orderId) {
        MallOrderOutputPay orderOutputPay = mallOrderDetailService.findByOrderId(orderId);
        if (orderOutputPay == null) {
            throw new BusinessException(PartyCode.IS_NO_DATA, "订单为空");
        }
        Date completeDate = new Date();
        for (MallOrderOutputParent orderOutput : orderOutputPay.getChildrens()) {
            MallOrderDetail pOut = mallOrderDetailService.get(orderOutput.getId());
            pOut.setStatus(MallOrderDetailStatus.STATUS_COMPLETE.getCode());
            pOut.setCompleteDate(completeDate);
            mallOrderDetailService.update(pOut);

            for (MallOrderOutputChild childOut : orderOutput.getChildrens()) {
                MallOrderDetail cOut = mallOrderDetailService.get(childOut.getId());
                cOut.setStatus(MallOrderDetailStatus.STATUS_COMPLETE.getCode());
                mallOrderDetailService.update(cOut);
            }
        }
    }
}
